using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Resources;
using Framework.Library.Core.Utils.Miscellaneous;

namespace Framework.Library.Core.Utils.Resources
{
    public class ResourceLoader : IResourceGetter
    {
        private readonly ResourceManager _resourceManager;

        public ResourceLoader(Assembly resourceAssembly)
        {
            ValidationUtils.ArgumentNotNull(resourceAssembly, "resourceAssembly");

            // assembly that resources are loader from is determined by the assembly of the assembly marker type
            string assemblyName = resourceAssembly.GetName().Name;

            var assemblyResourceNames = new List<string>(resourceAssembly.GetManifestResourceNames());

            var possibleResourceNames = new List<string>();
            // location in Microsoft assemblies
            possibleResourceNames.Add(assemblyName);
            // location of generated file in 2005 projects
            possibleResourceNames.Add(assemblyName + ".Properties.Resources");

            // look at a couple of locations for the resources file, loading the first one found
            foreach (string possibleResourceName in possibleResourceNames)
            {
                if (assemblyResourceNames.Contains(possibleResourceName + ".resources"))
                {
                    _resourceManager = new ResourceManager(possibleResourceName, resourceAssembly);
                    break;
                }
            }

            if (_resourceManager == null)
                throw new Exception(string.Format("Could not find embedded resource file for assembly {0}.",
                                                  assemblyName));
        }

        #region IResourceGetter Members

        public ResourceManager ResourceManager
        {
            get { return _resourceManager; }
        }

        public string GetString(string name)
        {
            string resourceValue = _resourceManager.GetString(name);

            if (resourceValue == null)
                throw new Exception(string.Format("Resource '{0}' not found in {1}.", name, _resourceManager.BaseName));

            return resourceValue;
        }

        public string GetString(string name, params object[] values)
        {
            string resourceValue = GetString(name);

            return string.Format(CultureInfo.CurrentCulture, resourceValue, values);
        }

        public object GetObject(string name)
        {
            object resourceValue = _resourceManager.GetObject(name);

            if (resourceValue == null)
                throw new Exception(string.Format("Resource '{0}' not found in {1}.", name, _resourceManager.BaseName));

            return resourceValue;
        }

        public T GetObject<T>(string name)
        {
            object value = GetObject(name);

            if (!(value is T))
                throw new Exception(string.Format("Resource '{0}' is of type {1}, not {2}.", name, value.GetType(),
                                                  typeof (T)));

            return (T) value;
        }

        #endregion
    }
}